/*!
    \file    main.c
    \brief   TLI_IPA display demo

    \version 2024-01-17, V2.6.4, demo for GD32F4xx
*/

/*
    Copyright (c) 2024, GigaDevice Semiconductor Inc.

    Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

    1. Redistributions of source code must retain the above copyright notice, this
       list of conditions and the following disclaimer.
    2. Redistributions in binary form must reproduce the above copyright notice,
       this list of conditions and the following disclaimer in the documentation
       and/or other materials provided with the distribution.
    3. Neither the name of the copyright holder nor the names of its contributors
       may be used to endorse or promote products derived from this software without
       specific prior written permission.

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "string.h"
#include "gd32f4xx.h"
#include "gd32f470z_eval.h"
#include "gd32f470z_lcd_eval.h"
#include "stdio.h"
#include "xpt2046_drv.h"
#include "softspi.h"
#include "awtk_config.h"

#define HORIZONTAL_SYNCHRONOUS_PULSE  10
#define HORIZONTAL_BACK_PORCH         30
#define ACTIVE_WIDTH                  480
#define HORIZONTAL_FRONT_PORCH        5

#define VERTICAL_SYNCHRONOUS_PULSE    2
#define VERTICAL_BACK_PORCH           2
#define ACTIVE_HEIGHT                 320
#define VERTICAL_FRONT_PORCH          4

uint16_t display_memory_front[ACTIVE_WIDTH*ACTIVE_HEIGHT];
extern void Xpt2046TouchAdjust(void);
extern int gui_app_start(int lcd_w, int lcd_h);

uint32_t awtk_mem[1024*300/4];
uint32_t timecount = 0;

static void tli_config(void);
static void tli_gpio_config(void);
static void lcd_config(void);
static void delay(uint32_t time);
void systick_config(void)
{
    /* setup systick timer for 1000Hz interrupts */
    if(SysTick_Config(SystemCoreClock / 1000U)) {
        /* capture error */
        while(1) {
        }
    }
    /* configure the systick handler priority */
    NVIC_SetPriority(SysTick_IRQn, 0x00U);
}
/*!
    \brief      main program
    \param[in]  none
    \param[out] none
    \retval     none
*/

void SetDisplayMemory(uint16_t* displayMemory,uint32_t size,uint16_t color)
{
		for(uint32_t i = 0;i<size;i++)
		{
				displayMemory[i] = color;
		}
}

void test(void);
extern touchPoint_t get_data(void);
int main(void)
{ 
		gd_eval_com_init(EVAL_COM0);
		touchPoint_t touchPoint = {0};
		systick_config();
		
		nvic_irq_enable(TLI_IRQn,0,0);
		
		lcd_config();
    tli_config();
    tli_layer_enable(LAYER0);
		
		tli_reload_config(TLI_FRAME_BLANK_RELOAD_EN);
		
#if USE_LCD_SYNC	
		tli_interrupt_enable(TLI_INT_LCR);
#endif
		
    tli_enable();
		printf("tli ok\r\n");
    
		MySPI_Init();
		Xpt2046TouchAdjust();
		
		SetDisplayMemory((uint16_t*)&display_memory_front[0],480,0x8000);
		
		gui_app_start(480,272);
    while(1){

    }
}

/*!
    \brief      LCD configuration
    \param[in]  none
    \param[out] none
    \retval     none
*/
static void lcd_config(void)
{
    /* configure the LCD control line */
    lcd_ctrl_line_config();
    lcd_disable();
    lcd_enable();
    
    /* configure the GPIO of TLI */
    tli_gpio_config();
    /* configure the LCD_SPI */
    lcd_spi_config(); 

    /* power on the LCD */

    /* power on the LCD */
#if defined(USE_LCD_VERSION_1_1)
    lcd_power_on();
#elif defined(USE_LCD_VERSION_1_2)
    lcd_power_on1();
#elif defined(USE_LCD_VERSION_1_3)
    lcd_power_on2();
#elif defined(USE_LCD_VERSION_1_4)
    lcd_power_on3();
#endif /* USE_LCD_VERSION_1_1 */

}

/*!
    \brief      configure TLI peripheral
    \param[in]  none
    \param[out] none
    \retval     none
*/
static void tli_config(void)
{
    tli_parameter_struct               tli_init_struct;
    tli_layer_parameter_struct         tli_layer_init_struct;

    /* initialize the parameters of structure */
    tli_struct_para_init(&tli_init_struct);
    tli_layer_struct_para_init(&tli_layer_init_struct);
    
    rcu_periph_clock_enable(RCU_TLI);
    tli_gpio_config();

    /* configure the PLLSAI clock to generate lcd clock */
    if(ERROR == rcu_pllsai_config(108, 2, 3)){
        while(1);
    }
    rcu_tli_clock_div_config(RCU_PLLSAIR_DIV4);
    rcu_osci_on(RCU_PLLSAI_CK);
    if(ERROR == rcu_osci_stab_wait(RCU_PLLSAI_CK)){
        while(1);
    }
    
    /* TLI initialization */
    tli_init_struct.signalpolarity_hs = TLI_HSYN_ACTLIVE_LOW;
    tli_init_struct.signalpolarity_vs = TLI_VSYN_ACTLIVE_LOW;
    tli_init_struct.signalpolarity_de = TLI_DE_ACTLIVE_LOW;
#if defined(USE_LCD_VERSION_1_3) || defined(USE_LCD_VERSION_1_4)
    tli_init_struct.signalpolarity_pixelck = TLI_PIXEL_CLOCK_INVERTEDTLI;
#else
    tli_init_struct.signalpolarity_pixelck = TLI_PIXEL_CLOCK_TLI;
#endif /* USE_LCD_VERSION_1_3 USE_LCD_VERSION_1_4 */
		
    tli_init_struct.synpsz_hpsz = HORIZONTAL_SYNCHRONOUS_PULSE - 1;
    tli_init_struct.synpsz_vpsz = VERTICAL_SYNCHRONOUS_PULSE - 1;
    tli_init_struct.backpsz_hbpsz = HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH - 1;
    tli_init_struct.backpsz_vbpsz = VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH - 1;
    tli_init_struct.activesz_hasz = HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH + ACTIVE_WIDTH - 1;
    tli_init_struct.activesz_vasz = VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH + ACTIVE_HEIGHT - 1;
    tli_init_struct.totalsz_htsz = HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH + ACTIVE_WIDTH + HORIZONTAL_FRONT_PORCH - 1;
    tli_init_struct.totalsz_vtsz = VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH + ACTIVE_HEIGHT + VERTICAL_FRONT_PORCH - 1;
    /* LCD background color configure */
    tli_init_struct.backcolor_red = 0xFF;
    tli_init_struct.backcolor_green = 0xFF;
    tli_init_struct.backcolor_blue = 0xFF; 
    tli_init(&tli_init_struct);

    /* TLI layer0 configuration */
    tli_layer_init_struct.layer_window_leftpos = (HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH);
    tli_layer_init_struct.layer_window_rightpos = (ACTIVE_WIDTH + HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH - 1);
    tli_layer_init_struct.layer_window_toppos = (VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH);
    tli_layer_init_struct.layer_window_bottompos = (ACTIVE_HEIGHT + VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH - 1);
    tli_layer_init_struct.layer_ppf = LAYER_PPF_RGB565;
    tli_layer_init_struct.layer_sa = 0xFF;
    tli_layer_init_struct.layer_default_blue = 0;
    tli_layer_init_struct.layer_default_green = 0;
    tli_layer_init_struct.layer_default_red = 0;
    tli_layer_init_struct.layer_default_alpha = 0x0;
    tli_layer_init_struct.layer_acf1 = LAYER_ACF1_PASA;
    tli_layer_init_struct.layer_acf2 = LAYER_ACF2_PASA;
#if 1
    tli_layer_init_struct.layer_frame_bufaddr = (uint32_t)&display_memory_front[0];
#else
		tli_layer_init_struct.layer_frame_bufaddr = (uint32_t)&image_ppm[60];
#endif	

		tli_layer_init_struct.layer_frame_line_length = (320*2);
    tli_layer_init_struct.layer_frame_buf_stride_offset = (320*2);
    tli_layer_init_struct.layer_frame_total_line_number = 480;
    tli_layer_init(LAYER0, &tli_layer_init_struct);
}

void layerSetNextBuf(uint32_t bufaddr)
{
		tli_reload_config(TLI_FRAME_BLANK_RELOAD_EN);
		tli_layer_parameter_struct         tli_layer_init_struct;
		/* TLI layer0 configuration */
    tli_layer_init_struct.layer_window_leftpos = (HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH);
    tli_layer_init_struct.layer_window_rightpos = (ACTIVE_WIDTH + HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH - 1);
    tli_layer_init_struct.layer_window_toppos = (VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH);
    tli_layer_init_struct.layer_window_bottompos = (ACTIVE_HEIGHT + VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH - 1);
    tli_layer_init_struct.layer_ppf = LAYER_PPF_RGB565;
    tli_layer_init_struct.layer_sa = 0xFF;
    tli_layer_init_struct.layer_default_blue = 0;
    tli_layer_init_struct.layer_default_green = 0;
    tli_layer_init_struct.layer_default_red = 0;
    tli_layer_init_struct.layer_default_alpha = 0x0;
    tli_layer_init_struct.layer_acf1 = LAYER_ACF1_PASA;
    tli_layer_init_struct.layer_acf2 = LAYER_ACF2_PASA;

    tli_layer_init_struct.layer_frame_bufaddr = (uint32_t)bufaddr;

		tli_layer_init_struct.layer_frame_line_length = (320*2);
    tli_layer_init_struct.layer_frame_buf_stride_offset = (320*2);
    tli_layer_init_struct.layer_frame_total_line_number = 480;
    tli_layer_init(LAYER0, &tli_layer_init_struct);

}

/*!
    \brief      configure TLI GPIO  
    \param[in]  none
    \param[out] none
    \retval     none
*/
static void tli_gpio_config(void)
{
    /* enable the periphral clock */
    rcu_periph_clock_enable(RCU_GPIOA);
    rcu_periph_clock_enable(RCU_GPIOB);
    rcu_periph_clock_enable(RCU_GPIOC);
    rcu_periph_clock_enable(RCU_GPIOD);
    rcu_periph_clock_enable(RCU_GPIOF);
    rcu_periph_clock_enable(RCU_GPIOG);

    /* configure HSYNC(PC6), VSYNC(PA4), PCLK(PG7), DE(PF10) */
    /* configure LCD_R7(PG6), LCD_R6(PA8), LCD_R5(PA12), LCD_R4(PA11), LCD_R3(PB0), 
                 LCD_G7(PD3), LCD_G6(PC7), LCD_G5(PB11), LCD_G4(PB10), LCD_G3(PG10), LCD_G2(PA6),
                 LCD_B7(PB9), LCD_B6(PB8), LCD_B5(PA3), LCD_B4(PG12), LCD_B3(PG11) */
    gpio_af_set(GPIOA,GPIO_AF_14,GPIO_PIN_3);
    gpio_af_set(GPIOA,GPIO_AF_14,GPIO_PIN_4);
    gpio_af_set(GPIOA,GPIO_AF_14,GPIO_PIN_6);
    gpio_af_set(GPIOA,GPIO_AF_14,GPIO_PIN_8);
    gpio_af_set(GPIOA,GPIO_AF_14,GPIO_PIN_11);
    gpio_af_set(GPIOA,GPIO_AF_14,GPIO_PIN_12);
    
    gpio_af_set(GPIOB,GPIO_AF_9,GPIO_PIN_0);
    gpio_af_set(GPIOB,GPIO_AF_14,GPIO_PIN_8);
    gpio_af_set(GPIOB,GPIO_AF_14,GPIO_PIN_9);
    gpio_af_set(GPIOB,GPIO_AF_14,GPIO_PIN_10);
    gpio_af_set(GPIOB,GPIO_AF_14,GPIO_PIN_11);
    
    gpio_af_set(GPIOC,GPIO_AF_14,GPIO_PIN_6);
    gpio_af_set(GPIOC,GPIO_AF_14,GPIO_PIN_7);
    
    gpio_af_set(GPIOD,GPIO_AF_14,GPIO_PIN_3);

    gpio_af_set(GPIOF,GPIO_AF_14,GPIO_PIN_10);
    
    gpio_af_set(GPIOG,GPIO_AF_14,GPIO_PIN_6);
    gpio_af_set(GPIOG,GPIO_AF_14,GPIO_PIN_7);
    gpio_af_set(GPIOG,GPIO_AF_9,GPIO_PIN_10);
    gpio_af_set(GPIOG,GPIO_AF_14,GPIO_PIN_11);
    gpio_af_set(GPIOG,GPIO_AF_9,GPIO_PIN_12);

    gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_6
                                |GPIO_PIN_8|GPIO_PIN_11|GPIO_PIN_12);
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_3|GPIO_PIN_4
                                |GPIO_PIN_6|GPIO_PIN_8|GPIO_PIN_11|GPIO_PIN_12);

    gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_0|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10
                                |GPIO_PIN_11);
    gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10
                                |GPIO_PIN_11);

    gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_6|GPIO_PIN_7);
    gpio_output_options_set(GPIOC, GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ, GPIO_PIN_6|GPIO_PIN_7);

    gpio_mode_set(GPIOD, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_3);
    gpio_output_options_set(GPIOD, GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ, GPIO_PIN_3);

    gpio_mode_set(GPIOF, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_10);
    gpio_output_options_set(GPIOF, GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ, GPIO_PIN_10);

    gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_10|GPIO_PIN_11
                                |GPIO_PIN_12);
    gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_10|GPIO_PIN_11
                                |GPIO_PIN_12);
}

/*!
    \brief      insert a delay time
    \param[in]  time: delay time length
    \param[out] none
    \retval     none
*/
void delay(uint32_t time)
{
    __IO uint32_t timecount = time;
    while(0 != timecount--);
}

#pragma __use_no_semihosting
struct __FILE
{
		int handle;
};

FILE __stdout;

void _sys_exit(int x)
{
		x = x;
}

int fputc(int ch, FILE *f)
{
    usart_data_transmit(EVAL_COM0, (uint8_t)ch);
    while(RESET == usart_flag_get(EVAL_COM0, USART_FLAG_TBE));
    return ch;
}
